{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "验证 same 方式"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[[[4., 1., 7., 5.],\n",
      "          [4., 4., 2., 5.],\n",
      "          [7., 7., 2., 4.],\n",
      "          [1., 0., 2., 4.]]]])\n",
      "torch.Size([1, 1, 4, 4])\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "\n",
    "# 1. 创建特征图\n",
    "# unsqueeze 指定在哪个位置添加维度\n",
    "input_feat = torch.tensor(\n",
    "    [[4, 1, 7, 5], [4, 4, 2, 5], [7, 7, 2, 4], [1, 0, 2, 4]], dtype=torch.float32).unsqueeze(0).unsqueeze(0)\n",
    "print(input_feat)\n",
    "print(input_feat.shape) #(批次, 通道数，高，宽)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Parameter containing:\n",
      "tensor([[[[ 0.4028,  0.3249],\n",
      "          [ 0.2992, -0.2405]]]], requires_grad=True)\n",
      "Parameter containing:\n",
      "tensor([-0.0197], requires_grad=True)\n"
     ]
    }
   ],
   "source": [
    "# 2. 创建一个 2×2 的卷积核\n",
    "conv2d = nn.Conv2d(in_channels=1,                       # 输入特征图的通道数\n",
    "                   out_channels=1, kernel_size=(2, 2),  # 输出特征图的通道数\n",
    "                   stride=1,                            # 滑动步长\n",
    "                   padding='same',                      # 补零方式；padding 为 valid 或 same 时，stride 必须为 1\n",
    "                   bias=True)                           # 是否使用偏移项\n",
    "# 默认情况随机初始化参数\n",
    "print(conv2d.weight)\n",
    "print(conv2d.bias)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Parameter containing:\n",
      "tensor([[[[1., 0.],\n",
      "          [2., 1.]]]])\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "# 人工强行干预卷积核的初始化\n",
    "conv2d = nn.Conv2d(1, 1, (2, 2), stride=1, padding='same', bias=False)\n",
    "# 卷积核要有四个维度（输入通道数、输出通道数、高、宽）\n",
    "kernels = torch.tensor([[[[1, 0], [2, 1]]]], dtype=torch.float32)\n",
    "conv2d.weight = nn.Parameter(kernels, requires_grad=False)\n",
    "print(conv2d.weight)\n",
    "print(conv2d.bias)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[[[16., 11., 16., 15.],\n",
      "          [25., 20., 10., 13.],\n",
      "          [ 9.,  9., 10., 12.],\n",
      "          [ 1.,  0.,  2.,  4.]]]])\n"
     ]
    }
   ],
   "source": [
    "# 3. 计算结果\n",
    "output = conv2d(input_feat)\n",
    "print(output)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.8.10 64-bit",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "c2561295c99b9e0691d04acbb6873b4734b14bb29878b65a5e35075f8e76500e"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
